package trigger

import (
	"bgs/db"
	sqlc "bgs/db/sqlc"
	nsqModel "bgs/nsqp/model"
	nsqpUtil "bgs/nsqp/util"
	orderService "bgs/service/order"
	userService "bgs/service/user"
	"bgs/util"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"github.com/nsqio/go-nsq"
	"go.uber.org/zap"
	"strconv"
)

var (
	lastSettleProfitedOrderMessage *nsqModel.CronMomentMessage = nil
)

// SettleProfitedOrderHandler 结算已分账订单 handler
type SettleProfitedOrderHandler struct {
	dao          *db.PgDao
	slog         *zap.SugaredLogger
	topic        string
	failover     *nsqpUtil.NsqFailover
	orderService *orderService.OrderServiceImp
	userService  *userService.UserServiceImp
}

// NewUpdateUserAccountOnAfterSaleExpireForOrderHandler create a new handler for CloseUnpayExpiredOrder
func NewSettleProfitedOrderHandler(
	pgdao *db.PgDao,
	slog *zap.SugaredLogger,
	topic string,
	failover *nsqpUtil.NsqFailover,
	orderService *orderService.OrderServiceImp,
	userService *userService.UserServiceImp,
) *SettleProfitedOrderHandler {
	return &SettleProfitedOrderHandler{
		dao:          pgdao,
		slog:         slog.With("module", "SettleProfitedOrderHandler"),
		topic:        topic,
		failover:     failover,
		orderService: orderService,
		userService:  userService,
	}
}

// HandleMessage implements the Handler interface.
func (h *SettleProfitedOrderHandler) HandleMessage(m *nsq.Message) error {
	if len(m.Body) == 0 {
		// Returning nil will automatically send a FIN command to NSQ to mark the message as processed.
		return nil
	}

	h.slog.Infof("SettleProfitedOrderHandlerMessage=>%s", string(m.Body))

	v := &nsqModel.CronMomentMessage{}
	if decodeErr := json.NewDecoder(bytes.NewReader(m.Body)).Decode(v); decodeErr != nil {
		return fmt.Errorf("无法解析信息[SettleProfitedOrderMessage]: %v", decodeErr)
	}
	if lastSettleProfitedOrderMessage != nil && lastSettleProfitedOrderMessage.TS >= v.TS {
		h.slog.Infof("过时的消息: lastSettleProfitedOrderMessage.TS:%v,v.TS:%v", lastSettleProfitedOrderMessage.TS, v.TS)
		return nil
	}

	reqID := strconv.FormatInt(v.TS, 10)
	ctx := context.WithValue(context.Background(), util.RequestID{}, reqID)

	var err error
	defer h.failover.BackupSubMsgWhenHandleFail(ctx, &err, nsqpUtil.BackupSubMsgParam{
		Ts:    v.TS,
		Topic: h.topic,
		Mbody: m.Body,
	})

	err = h.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		limit := util.Int32IfThenElse(v.Data.Limit > 0, v.Data.Limit, 5)
		orders, err := q.ListOrdersOfProfitedAndUnSettledAtAfterSaleExpiredToLock(ctx, limit)
		if err != nil {
			return
		}
		count := len(orders)
		if count > 0 {
			for _, order := range orders {
				err = h.userService.SettleOrderProfitLogs(ctx, q, &order)
				if err != nil {
					return
				}
				h.slog.Infof("A 用户账户结算分账订单ok")
				err = h.orderService.MarkOrderSettled(ctx, q, order.ID)
				if err != nil {
					return
				}
				h.slog.Infof("B 标记分账订单已结算")
			}
		}
		h.slog.Infof("a SettleProfitedOrderHandler-结算订单(%d条) ok", count)
		return
	})

	if err != nil {
		return err
	}
	lastSettleProfitedOrderMessage = v
	// Returning a non-nil error will automatically send a REQ command to NSQ to re-queue the message.
	return nil
}
